package cn.sc.summer.construction.sysimpl;

import cn.sc.summer.constant.email.EmailConstant;
import cn.sc.summer.constant.rabbit.RabbitConstant;
import cn.sc.summer.daoapi.dao.SqlMapper;
import cn.sc.summer.email.util.EmailUtil;
import cn.sc.summer.mybatis.po.Sql;
import cn.sc.summer.protocol.prometheus.SysPrometheusMonitor;
import cn.sc.summer.rabbitmq.enums.RabbitErrorMessageTypeEnum;
import cn.sc.summer.rabbitmq.po.RabbitMessage;
import cn.sc.summer.rabbitmq.service.RabbitConsumerService;
import cn.sc.summer.rabbitmq.util.RabbitUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.type.TypeReference;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.velocity.VelocityContext;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;

/**
 * 类名：sql捕获监听实现类
 *
 * @author a-xin
 * @date 2023/10/1 17:14
 */
@Slf4j
@Service
public class SqlServiceImpl extends RabbitConsumerService {

    @Resource
    private SqlMapper sqlMapper;

    @Resource
    private SysPrometheusMonitor sysPrometheusMonitor;

    /**
     * 接口: 监听日志发布消息，将SQL日志信息进行异步入库处理
     *
     * @param jsonStr 日志信息
     * @param message rabbit消息提
     * @param channel rabbit信道
     * @author a-xin
     * @date 2023/9/23 15:48
     */
    @RabbitListener(queues = RabbitConstant.SQL_RECORD_QUEUE)
    public void consumer(String jsonStr, Message message, Channel channel) {
        try {
            sysPrometheusMonitor.getErrorSqlCount().increment();
            RabbitMessage<JSONObject> jsonObjectRabbitMessage = RabbitUtil.checkMessage(jsonStr, new TypeReference<JSONObject>() {});
            channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
            if (jsonObjectRabbitMessage.getFlag()) {
                JSONObject sqlInfo = jsonObjectRabbitMessage.getMessage();
                String subject = "SQL执行异常报告";
                Map<String, String> data = new HashMap<>();
                data.put("访问地址IP", sqlInfo.getString("reqIp"));
                data.put("操作URI", sqlInfo.getString("reqUri"));
                data.put("SQL所在服务名称", sqlInfo.getString("apiServiceName"));
                data.put("原始SQL", sqlInfo.getString("originalSql"));
                data.put("执行SQL参数", sqlInfo.getString("params"));
                data.put("最终执行SQL参数信息", sqlInfo.getString("executeSql"));
                data.put("执行SQL耗时", sqlInfo.getString("time") + "mm");
                VelocityContext emailTemplateParam = EmailUtil.createEmailTemplateParam(subject, data);

                String out = EmailUtil.velocityEmailText(emailTemplateParam, "/email.html.vm");
                EmailUtil.sendComplexMail(EmailConstant.EMAIL_ADDRESS, "SQL执行异常报告", out);

                Sql sql = JSONObject.parseObject(jsonStr, Sql.class);
                sqlMapper.insert(sql);
            } else {
                log.error("==> 接收到重复消费消息：Queue: {}, Exchange : {}, RoutingKey : {}, Message : {}",
                        RabbitConstant.SQL_RECORD_QUEUE,
                        RabbitConstant.SQL_RECORD_EXCHANGE,
                        RabbitConstant.SQL_RECORD_ROUTING_KEY,
                        jsonStr);
            }
        } catch (Exception e) {
            e.printStackTrace();
            rabbitErrorService.exchangeMessage(e.getMessage(), jsonStr, RabbitErrorMessageTypeEnum.SLOW_SQL_WRITE_ERROR);
        }
    }

}
